﻿using FluentParser.Expressions;
using FluentParser.Expressions.Terminals.Parsing;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace FluentParser.Tests.Expressions.Terminals.Parsing
{
    [TestClass]
    public class ParseRegexSymbolTerminalTests
    {
        [TestMethod]
        public void Parse_WhenParsingValidText_ShouldReturnTheText()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("ValidText");
            ParsingResult<object> result = token.Parse("ValidTextFollowedBySomethingElse");
            var expected = "ValidText";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, result.Length);
        }

        [TestMethod]
        public void Parse_WhenParsingInvalidText_ShouldReturnNull()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("InvalidText");

            var expected = (ParsingResult<string>)null;
            var actual = token.Parse("SomethingElse");

            Assert.AreEqual(expected, actual);
        }

        [TestMethod]
        public void Parse_WhenParsingASentenceUsingAlphaRegex_ShouldReturnTheFirstWord()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("[A-Za-z]+");
            ParsingResult<object> result = token.Parse("This is a sentence.");

            var expected = "This";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, result.Length);
        }

        [TestMethod]
        public void Parse_WhenParsingANumberWithIntegerConversion_ShouldReturnAnInteger()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("[0-9]+");
            ParsingResult<object> result = token.Parse("1234SomethingElse");

            var expected = "1234";
            var actual = result.Value;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(4, result.Length);
        }

        [TestMethod]
        public void ParseNode_WhenParsingValidText_ShouldReturnTheText()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("ValidText");
            ParsingNodeResult node = token.ParseNode("ValidTextFollowedBySomethingElse");

            string expected = "ValidText";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, node.Length);
        }

        [TestMethod]
        public void ParseNode_WhenParsingInvalidText_ShouldReturnNull()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("InvalidText");
            ParsingNodeResult node = token.ParseNode("SomethingElse");

            string expected = null;
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(0, node.Length);

            // BUG: ExploredLength is wrong because Regex doesn't provide this information
            //Assert.AreEqual(1, node.ExploredLength);
        }

        [TestMethod]
        public void ParseNode_WhenParsingASentenceUsingAlphaRegex_ShouldReturnTheFirstWord()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("[A-Za-z]+");
            ParsingNodeResult node = token.ParseNode("This is a sentence.");

            string expected = "This";
            string actual = node.Value as string;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(expected.Length, node.Length);
        }

        [TestMethod]
        public void ParseNode_WhenParsingANumberWithIntegerConversion_ShouldReturnAnInteger()
        {
            ParseRegexSymbolTerminal token = new ParseRegexSymbolTerminal("[0-9]+");
            ParsingNodeResult node = token.ParseNode("1234SomethingElse");

            var expected = "1234";
            var actual = node.Value;

            Assert.AreEqual(expected, actual);
            Assert.AreEqual(4, node.Length);

            // BUG: ExploredLength is wrong because Regex doesn't provide this information
            //Assert.AreEqual(5, node.ExploredLength);
        }
    }
}